local snow     = require("meet_your_mods.mhr").snow
local status   = require("meet_your_mods.status")
local shortcut = require("meet_your_mods.shortcut")
local routine  = require("meet_your_mods.routine_framework")
local ui       = require("meet_your_mods.ui")

snow.data.EquipmentInventoryData:fetch_method("set_talisman_id", "setId(snow.data.DataDef.PlTalismanId)")
snow.data.WishListManager.WishInfoList:fetch_method("set_equipment",
    "setWishData(System.Int32, snow.data.WishListManager.WishDataType, snow.data.PlEquipMakingData)")
snow.data.WishListManager.WishInfoList:fetch_method("set_hyakuryu",
    "setWishData(System.Int32, snow.data.WishListManager.WishDataType, snow.data.PlHyakuryuSkillRecipeData, snow.data.ContentsIdSystem.WeaponId)")
snow.data.WishListManager.WishInfoList:fetch_method("set_deco",
    "setWishData(System.Int32, snow.data.WishListManager.WishDataType, snow.data.DecorationsData)")

local inventory = {
    config         = nil,
    categories     = {
        support  = "支援・回复　",
        bullet   = "弹・瓶　　　",
        mystery  = "炼金・怪异化",
        mineral  = "矿石・铠玉　",
        currency = "通货・换金　",
        monster  = "怪物通用　　",
        boss     = "大型怪物　　",
        zako     = "小型怪物　　",
        common   = "常规　　　　",
        scrap    = "端材　　　　",
        event    = "活动　　　　",
        wishlist = "愿望单　　　",
    },
    category_index = {
        "support",
        "bullet",
        "mystery",
        "mineral",
        "currency",
        "monster",
        "boss",
        "zako",
        "common",
        "scrap",
        "event",
        "wishlist",
    },

    index = 1,
    items = nil,
}

--读取玩家道具箱
function inventory:load_items()
    if not self.config then
        self.items = nil
        self.index = 1
        return
    end

    local items = {}
    for _, item in pairs(shortcut:get_item_inventory()) do
        if not item:isEmpty() then
            items[item:getItemId()] = {
                quantity  = item:getNum(),
                inventory = item,
            }
        end
    end

    self.items = items
end

--获取道具数据和数量
function inventory:get_item_quantity(item_id)
    local item = self.items[item_id]
    return item and item.quantity or 0, item
end

--设置道具数量
function inventory:set_item_quantity(item, item_id, quantity)
    item = item or self.items[item_id]

    if not item then
        shortcut:add_item_to_box(item_id, quantity)
        item = {
            quantity  = quantity,
            inventory = snow.data.DataManager:get_singleton():getItemBox():findInventoryData(item_id),
        }
        self.items[item_id] = item
        return
    end

    item.inventory:setNum(quantity, true)
    if 0 == quantity then
        self.items[item_id] = nil
        return
    end
    item.quantity = quantity
end

--填充所需素材
function inventory:fill_wishlist()
    local wishlist = self.config.wishlist[1]
    for _, wihsh_item in pairs(wishlist) do
        local quantity, item = self:get_item_quantity(wihsh_item.id)
        if wihsh_item.need > quantity then
            self:set_item_quantity(item, wihsh_item.id, wihsh_item.need)
        end
    end
end

--读取道具数据
function inventory:load_category_config(config)
    local category = {}
    local uuid     = ui:generate_uuid(category)
    for index, item in pairs(config) do
        if "table" == type(item) then
            category[index] = self:load_category_config(item)
        else
            category[index] = {
                id   = item,
                name = shortcut:get_item_name(item),
                uuid = uuid .. "/" .. item,
            }
        end
    end

    return category
end

--查询怪物素材列表节点
function inventory:get_monster_material_list(config, enemy)
    local monster_list = shortcut:is_boss_enemy(enemy)
        and config.boss or config.zako

    local name = shortcut:get_enemy_name(enemy)
    for _, monster in pairs(monster_list) do
        if name == monster.name then
            return monster
        end
    end

    local monster = {
        id        = enemy,
        name      = name,
        uuid      = ui:generate_uuid(),
        checklist = {},
        materials = {},
    }
    table.insert(monster_list, monster)

    return monster
end

--读取给定怪物的素材列表
function inventory:load_monster_materials(config, rewards)
    local monster = self:get_monster_material_list(config, rewards._EmTypes)

    rewards = {
        rewards._TargetRewardItemIdList,
        rewards._HagitoriRewardItemIdList,
        rewards._CaptureRewardItemIdList,
        rewards._PartsBreakRewardItemIdList,
        rewards._DropRewardItemIdList,
    }

    for _, reward in pairs(rewards) do
        for _, material in pairs(reward) do
            if snow.data.ContentsIdSystem.ItemId.none == material
                or shortcut:get_item_type(material) ~= snow.data.DataDef.ItemTypes.Material
            then
                goto next_item
            end

            if not monster.checklist[material] then
                monster.checklist[material] = true
                table.insert(monster.materials, {
                    id   = material,
                    name = shortcut:get_item_name(material),
                    uuid = monster.uuid .. "/" .. material,
                })
            end
            ::next_item::
        end
    end

    table.sort(monster.materials, function(left, right) return left.name < right.name end)
end

--读取怪物素材列表
function inventory:load_monster_config(config)
    config.boss = {}
    config.zako = {}

    local lot_data_manager = snow.data.LotDataManager:get_singleton()
    local reward_list      = {
        lot_data_manager._MonsterLotTableDataMR._Param,
        lot_data_manager._MonsterLotTableData._Param,
    }

    for _, rank in pairs(reward_list) do
        for _, rewards in pairs(rank) do
            self:load_monster_materials(config, rewards)
        end
    end

    table.sort(config.boss, function(left, right)
        return left.name < right.name
    end)
    table.sort(config.zako, function(left, right)
        return left.name < right.name
    end)

    local mystery           = {}
    local mystery_checklist = {}
    local mystery_uuid      = ui:generate_uuid(mystery)
    for _, reward in pairs(lot_data_manager._MysteryRewardItemUserData._Param) do
        if reward._RewardItem ~= snow.data.ContentsIdSystem.ItemId.none
            and not mystery_checklist[reward._RewardItem]
        then
            mystery_checklist[reward._RewardItem] = true
            table.insert(mystery, {
                id   = reward._RewardItem,
                name = shortcut:get_item_name(reward._RewardItem),
                uuid = mystery_uuid .. "/" .. reward._RewardItem,
            })
        end
    end
    table.insert(config.mystery, mystery)
end

--读取愿望单素材表
function inventory:load_wishlist(config, refresh_system)
    local wishlist_manager = snow.data.WishListManager:get_singleton()
    if not wishlist_manager then
        config.wishlist = { {} }
        return
    end

    if refresh_system then
        wishlist_manager:calcWishListDataItemsCount()
    end
    if wishlist_manager:isEmptyAll() then
        config.wishlist = { {} }
        return
    end

    local items    = {}
    local wishlist = wishlist_manager._TotalItems
    local uuid     = ui:generate_uuid(items)
    for index = 1, wishlist.TotalItemsCount do
        local item = wishlist.sortItems[index]
        table.insert(items, {
            id   = item._Id,
            need = item._Num,
            name = shortcut:get_item_name(item._Id),
            uuid = uuid .. "/" .. item._Id,
        })
    end
    config.wishlist = { items, }
end

--读取道具分类表
function inventory:load_config()
    if self.config then
        return
    end

    local static_config = json.load_file("meet_your_mods.item")
    if not static_config then
        error("invalid file: reframework/data/meet_your_mods.item")
    end

    local config = self:load_category_config(static_config)
    self:load_monster_config(config)
    self:load_wishlist(config, true)

    self.config = config
end

function inventory:toggle_window()
    if self.items then
        self.items = nil
    else
        self:load_items()
    end
end

function inventory:draw_controller(current, min, max, text)
    if imgui.button("＜") then
        current = current - 1 >= min and current - 1 or max
    end

    imgui.same_line()
    imgui.text(text)

    imgui.same_line()
    if imgui.button("＞") then
        current = current + 1 <= max and current + 1 or 1
    end

    return current
end

function inventory:draw_quantity(item_id, need, uuid)
    local quantity, item = self:get_item_quantity(item_id)

    imgui.push_id(uuid)
    local changed, value = imgui.input_text(need or nil, quantity, 1)
    imgui.pop_id()

    value = tonumber(value)
    if not changed or not value
        or value < 0 or value > 9999
        or value == quantity
    then
        return
    end
    self:set_item_quantity(item, item_id, value)
end

--绘制道具表格
function inventory:draw_table(category)
    if not imgui.begin_table(nil, 6, imgui.TableFlags.NoSavedSettings | imgui.TableFlags.RowBg) then return end

    for _, item in pairs(category) do
        imgui.table_next_column()
        imgui.text(item.name)

        imgui.table_next_column()
        self:draw_quantity(item.id, item.need, item.uuid)
    end
    imgui.end_table()
end

--绘制道具箱窗口
function inventory:draw_window()
    imgui.spacing()
    imgui.indent(4)

    local category = self.category_index[self.index]
    self.index     = self:draw_controller(self.index, 1, #self.category_index, self.categories[category])

    imgui.same_line()
    imgui.spacing()
    imgui.same_line()
    if imgui.button("刷新") then
        self:load_items()
    end

    if "wishlist" == category then
        imgui.same_line()
        imgui.spacing()
        imgui.same_line()
        if imgui.button("填充所需素材") then
            self:fill_wishlist()
        end
    end

    imgui.spacing()
    for _, sub_category in pairs(self.config[category]) do
        if "boss" == category or "zako" == category then
            imgui.push_id(sub_category.uuid)
            if imgui.tree_node(sub_category.name) then
                self:draw_table(sub_category.materials)
                imgui.tree_pop()
                imgui.spacing()
            end
            imgui.pop_id()
        else
            self:draw_table(sub_category)
            imgui.text(" ")
        end
    end
end

function inventory:pre_return_title(_)
    self.config = nil
    self.index  = 1
    self.items  = nil
end

function inventory:post_before_village(_)
    self:load_config()
end

function inventory:initialize()
    routine:hook(self)

    snow.data.WishListManager.calcWishListDataItemsCount:sdk_hook(nil, function(result)
        if self.config then
            self:load_wishlist(self.config)
        end
        return result
    end)

    local refresh_wishlist = function(result)
        snow.data.WishListManager:get_singleton():calcWishListDataItemsCount()
        return result
    end
    snow.data.WishListManager.WishInfoList.set_equipment:sdk_hook(nil, refresh_wishlist)
    snow.data.WishListManager.WishInfoList.set_hyakuryu:sdk_hook(nil, refresh_wishlist)
    snow.data.WishListManager.WishInfoList.set_deco:sdk_hook(nil, refresh_wishlist)
    snow.data.WishListManager.deleteWishData:sdk_hook(nil, refresh_wishlist)

    if status:current_status() ~= status.logical_status.none then
        self:post_before_village()
    end

    ui:cluster("inventory", "存档功能")
    ui:button("inventory", "修改道具", function() self:toggle_window() end)

    ui:child_window(function() return self.items end, function() self:toggle_window() end,
        "道具修改", self.draw_window, self)
end

function inventory:normalize()
end

return inventory
